/*
	NanoStack: MCU software and PC tools for sensor networking.

	Copyright (C) 2006-2007 Sensinode Ltd.

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the Free Software Foundation, Inc.,
	51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

		Address:
		Sensinode Ltd.
		PO Box 1
		90571 Oulu, Finland

		E-mail:
		info@sensinode.com
*/


/* Standard includes. */
#include <stdlib.h>
#include <string.h>

/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

#include <sys/inttypes.h>

#include "stack.h"
#include "uart.h"
#include "rf.h"
#include "bus.h"

#ifdef HAVE_DMA
#include "dma.h"
#endif

#include "debug.h"

#include "adc.h"

/*-----------------------------------------------------------*/

static void vSendingTask(int8_t* pvParameters);
static void vReceivingTask(int8_t* pvParameters);

static uint16_t Sensing();
static void SendToAdapter(uint16_t sensedValue);
static uint16_t ReceiveFromAdapter();
static void ChangePolicy(uint16_t policy);

uint16_t DELAY = 370;

socket_t* sendingSocket = 0;
socket_t* receivingSocket = 0;
buffer_t* sendingBuf = 0;
buffer_t* receivingBuf = 0;


sockaddr_t src_address =
{
	ADDR_802_15_4_PAN_LONG,
	{
		0xFF, 0xFF, 0xFF, 0xFF,
		0xFF, 0xFF, 0x00, 0x01
	},
	61619
};

sockaddr_t dst_address =
{
	ADDR_802_15_4_PAN_LONG,
	{
		0xFF, 0xFF, 0xFF, 0xFF,
		0xFF, 0xFF, 0x00, 0x00
	},
	61620
};

int main( void )
{	
	bus_init();
	
	stack_init();
	
	debug_init(115200);

	xTaskCreate(vSendingTask, "Sending", configMAXIMUM_STACK_SIZE, NULL, (tskIDLE_PRIORITY+0), (xTaskHandle*)NULL);
	xTaskCreate(vReceivingTask, "Receiving", configMAXIMUM_STACK_SIZE, NULL, (tskIDLE_PRIORITY+0), (xTaskHandle*)NULL);

	vTaskStartScheduler();

	return 0;
}

static void vSendingTask(int8_t *pvParameters )
{
	uint16_t sensedValue = 0;
	adc_init();
	
	sendingSocket = socket(MODULE_CUDP, 0);
	sendingBuf = socket_buffer_get(sendingSocket);
	
	debug("Sending task start.\r\n");
	
				
	for(;;){		
		vTaskDelay(DELAY/portTICK_RATE_MS);
		sensedValue = Sensing();
		SendToAdapter(sensedValue);
	}
}

static uint16_t Sensing()
{	
	int16_t temp = 0;
	ADCCON1 = 0x73;
		
	// ADCCON1 |= 0x40;
	// ADCCON1 |= 0x40;
	ADCCON3 = 0x3F;
	//ADCCON3 = 0xB7;
	
	ADCCFG = (0x01<<4);
	debug_printf("%X, %X, %X, %X\r\n", ADCCON1, ADCCON2, ADCCON3, ADCCFG);
	// debug_hex(ADCCON1);
	// debug_hex(ADCCON2);
	// debug_hex(ADCCON3);	
	// debug_hex(ADCCFG);
	
	while(!(ADCCON1 & 0x80))
	
	temp = ADCH << 8;
	temp |= ADCL;
	
	debug_printf("Sensor_value (hex) = %X, (int) = %d\r\n", temp, temp);
	// debug("Light Sensor_value  (hex) = ");
	// debug_hex(temp);
	// debug("  (int) = ");
	// `debug_int(temp);
	// debug("\r\n");
	
		
	return temp;
}

static void SendToAdapter(uint16_t sensedValue)
{	
	int retry = 0;
	
	sendingBuf->buf[sendingBuf->buf_end++] = (sensedValue >> 8);
	sendingBuf->buf[sendingBuf->buf_end++] = (uint8_t) sensedValue;
	
	LED2_OFF();
	if ((socket_sendto(sendingSocket, &dst_address, sendingBuf)==pdFALSE)&&(retry<3)){
		vTaskDelay(5/portTICK_RATE_MS);
		retry++;
	}
	if(retry>=3){
		debug("Failed sending.\r\n");
		socket_buffer_free(sendingBuf);
	}
	else{
		debug_int(sensedValue);
		debug(" sent.\r\n");
	}
	LED2_ON();
}

static void vReceivingTask(int8_t *pvParameters)
{
	uint16_t policy = 0;
	debug("Receiving task start.\r\n");
	
	receivingSocket = socket(MODULE_CUDP, 0);
	socket_bind(receivingSocket, &src_address);
	
	for(;;){
		if(policy = ReceiveFromAdapter()){
			ChangePolicy(policy);u
		}
	}
}

static uint16_t ReceiveFromAdapter()
{
	uint16_t temp = 0;
	receivingBuf = socket_read(receivingSocket, 10);
	if(receivingBuf){
		LED1_OFF();
		temp = (uint16_t)(receivingBuf->buf[receivingBuf->buf_ptr]) << 8;
		temp |= receivingBuf->buf[receivingBuf->buf_ptr+1];
		vTaskDelay(5/portTICK_RATE_MS);
		
		debug_printf("%d recv.\r\n", temp);

		// debug_int(temp);
		// debug(" recv.\r\n");
		LED1_ON();
	}
	socket_buffer_free(receivingBuf);
	receivingBuf = 0;
	return temp;
}

static void ChangePolicy(uint16_t policy)
{
	DELAY = policy;
}
